﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.ComponentModel;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Workflow;
using Microsoft.Crm.Sdk;
using System.Workflow.ComponentModel.Compiler;
using System.IO;
using Microsoft.Crm.Sdk.Query;

namespace CrmContrib.Workflow.Activities.Communications
{
    [CrmWorkflowActivity("Add File Attachment to E-mail", "CrmContrib \\ Communications")]
    public class AddFileAttachmentToEmailActivity : Activity
    {
        [CrmInput("E-mail")]
        [CrmReferenceTarget("email")]
        [ValidationOption(ValidationOption.Required)]
        public Lookup Email
        {
            get { return (Lookup)base.GetValue(AddFileAttachmentToEmailActivity.EmailProperty); }
            set { base.SetValue(AddFileAttachmentToEmailActivity.EmailProperty, value); }
        }

        public static readonly DependencyProperty EmailProperty = DependencyProperty.Register("Email", typeof(Lookup), typeof(AddFileAttachmentToEmailActivity));

        [CrmInput("File ID")]
        [ValidationOption(ValidationOption.Required)]
        public string FileID
        {
            get { return (string)base.GetValue(AddFileAttachmentToEmailActivity.FileIDProperty); }
            set { base.SetValue(AddFileAttachmentToEmailActivity.FileIDProperty, value); }
        }

        public static readonly DependencyProperty FileIDProperty = DependencyProperty.Register("FileID", typeof(string), typeof(AddFileAttachmentToEmailActivity));

        [CrmInput("File Name")]
        [ValidationOption(ValidationOption.Required)]
        public string FileName
        {
            get { return (string)base.GetValue(FileNameProperty); }
            set { base.SetValue(FileNameProperty, value); }
        }

        public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register("FileName", typeof(string), typeof(AddFileAttachmentToEmailActivity));

        [CrmInput("Mime Type")]
        [ValidationOption(ValidationOption.Required)]
        public string MimeType
        {
            get { return (string)base.GetValue(MimeTypeProperty); }
            set { base.SetValue(MimeTypeProperty, value); }
        }

        public static readonly DependencyProperty MimeTypeProperty = DependencyProperty.Register("MimeType", typeof(string), typeof(AddFileAttachmentToEmailActivity));

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            var contextService = executionContext.GetService<IContextService>();
            var workflowContext = contextService.Context;
            var service = workflowContext.CreateCrmService();

            var entry = FileRegistry.GetFile(this.FileID);
            var attachmentNumber = this.GetNextAttachmentNumber(service, this.Email.Value);

            var attachment = new activitymimeattachment();
            attachment.mimetype = this.MimeType;
            attachment.attachmentnumber = CrmTypes.CreateCrmNumber(attachmentNumber);
            attachment.subject = this.FileName;
            attachment.filename = this.FileName;

            attachment.activityid = this.Email;

            var data = File.ReadAllBytes(entry.FileName);            
            attachment.body = Convert.ToBase64String(data);

            var file = new FileInfo(entry.FileName);
            attachment.filesize = CrmTypes.CreateCrmNumber((int)file.Length);

            service.Create(attachment);

            return base.Execute(executionContext);
        }

        private int GetNextAttachmentNumber(ICrmService service, Guid emailID)
        {
            var columns = new ColumnSet();
            columns.AddColumn("activityid");
            columns.AddColumn("attachmentnumber");

            var condition = new ConditionExpression();
            condition.AttributeName = "activityid";
            condition.Operator = ConditionOperator.Equal;
            condition.Values = new string[] { emailID.ToString() };
            
            var filter = new FilterExpression();
            filter.AddCondition(condition);

            var query = new QueryExpression();
            query.EntityName = EntityName.activitymimeattachment.ToString();
            query.Criteria = filter;
            query.ColumnSet = columns;

            var attachments = service.RetrieveMultiple(query);
            var maxAttachmentNumber = attachments.BusinessEntities.Cast<activitymimeattachment>().Max(a => a.attachmentnumber);

            return maxAttachmentNumber == null ? 1 : maxAttachmentNumber.Value + 1;
        }
    }
}
